package com.example.score.utils;

import com.example.score.service.ScoreAnalysisService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ExcelGenerator {

    public static void main(String[] args) {
        // 模拟接口返回的数据，这里你可以替换成实际从接口获取的数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        // 以下是你提供的一条数据示例，可根据实际情况扩展多条数据
        Map<String, Object> data = new HashMap<>();
        dataList.add(data);

        generateExcel(dataList, "作业得分表.xlsx", 0);
    }

    public static void generateExcel(List<Map<String, Object>> dataList, String filePath, Integer type) {
        // 创建工作簿和工作表
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("作业得分表");

        // 创建样式
        CellStyle headerStyle = createHeaderStyle(workbook);
        CellStyle dataStyle = createDataStyle(workbook);

        // 1. 收集所有试题名称（客观题和主观题）
        Set<String> allObjectiveQuestions = new LinkedHashSet<>(); // 保持顺序
        Set<String> allSubjectiveQuestions = new LinkedHashSet<>();
        for (Map<String, Object> data : dataList) {
            Map<String, Object> objectiveAnswerMap = new LinkedHashMap<>();
            Map<String, Object> subjectiveMap = new LinkedHashMap<>();
            //这里结构不一样所以加一个type 进行判断
            if(type == 0) {
                // 尝试获取 objectiveMap 并转换为 Map<String, Double>
                Object objectiveMapObj = data.get("objectiveMap");
                if (objectiveMapObj instanceof Map) {
                    try {
                        // 这里明确转换类型，确保是 Map<String, Double> 类型
                        Map<String, Double> tempObjectiveMap = (Map<String, Double>) objectiveMapObj;
                        objectiveAnswerMap.putAll(tempObjectiveMap);
                    } catch (ClassCastException e) {
                        // 处理类型转换异常，比如实际值不是 Double 类型等情况
                        e.printStackTrace();
                        // 可以根据需求选择是否继续，或者进行默认值处理等
                    }
                }

                // 尝试获取 subjectiveMap 并转换为 Map<String, Double>
                Object subjectiveMapObj = data.get("subjectiveMap");
                if (subjectiveMapObj instanceof Map) {
                    try {
                        Map<String, Double> tempSubjectiveMap = (Map<String, Double>) subjectiveMapObj;
                        subjectiveMap.putAll(tempSubjectiveMap);
                    } catch (ClassCastException e) {
                        e.printStackTrace();
                    }
                }
            }else {
                //list 转成map
                List<Map<String, Object>> objList = (List<Map<String, Object>>) data.get("objectiveMap");
                List<Map<String, Object>> subList = (List<Map<String, Object>>) data.get("subjectiveMap");
                objList = objList.stream().sorted(Comparator.comparing(Map<String, Object>::toString).reversed()).collect(Collectors.toList());
                subList = subList.stream().sorted(Comparator.comparing(Map<String, Object>::toString).reversed()).collect(Collectors.toList());
                // 转换客观题列表为Map（题号→分数）
                objectiveAnswerMap = new TreeMap<>(new ScoreAnalysisService.QuestionKeyComparator());
                if (objList != null) {
                    for (Map<String, Object> item : objList) {
                        String questionNum = item.get("questionNum").toString();
                        Object scoreObj = item.get("score");
                        if (questionNum != null && scoreObj != null) {
                            // 确保分数转换为Integer
                            if (scoreObj instanceof Number) {
                                objectiveAnswerMap.put(questionNum, scoreObj);
                            } else if (scoreObj instanceof String) {
                                try {
                                    objectiveAnswerMap.put(questionNum, scoreObj);
                                } catch (NumberFormatException e) {
                                    // 处理格式错误，可记录日志或设置默认值
                                    objectiveAnswerMap.put(questionNum, "0");
                                }
                            }
                        }
                    }
                }
                // 转换主观题列表为Map（题号→分数）
                subjectiveMap = new TreeMap<>(new ScoreAnalysisService.SubQuestionKeyComparator());
                if (subList != null) {
                    for (Map<String, Object> item : subList) {
                        String questionNum = (String) item.get("questionNum");
                        Object scoreObj = item.get("score");
                        if (questionNum != null && scoreObj != null) {
                            // 确保分数转换为Integer
                            if (scoreObj instanceof Number) {
                                subjectiveMap.put(questionNum, scoreObj.toString());
                            } else if (scoreObj instanceof String) {
                                try {
                                    subjectiveMap.put(questionNum, scoreObj);
                                } catch (NumberFormatException e) {
                                    // 处理格式错误，可记录日志或设置默认值
                                    subjectiveMap.put(questionNum, "0");
                                }
                            }
                        }
                    }
                }
            }
            allObjectiveQuestions.addAll(objectiveAnswerMap.keySet());
            allSubjectiveQuestions.addAll(subjectiveMap.keySet());
        }

        // 2. 构建表头
        // 第一行表头（动态创建）
        // 动态计算客观题和主观题的数量
        int objectiveCount = allObjectiveQuestions.size();
        int subjectiveCount = allSubjectiveQuestions.size();
        Row row0 = sheet.createRow(0);
        int firstLevelHeaderLength = 6 + objectiveCount + subjectiveCount;
        String[] firstLevelHeaders = new String[firstLevelHeaderLength];
        firstLevelHeaders[0] = "姓名";
        firstLevelHeaders[1] = "全体排名";
        firstLevelHeaders[2] = "班级排名";
        firstLevelHeaders[3] = "总得分";
        // 合并总得分相关的单元格
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 3, 5));

        // 合并考号、姓名、排名单元格
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1));
        sheet.addMergedRegion(new CellRangeAddress(0, 1, 2, 2));

        int objectiveStartCol = 6;
        if (objectiveCount > 1) {
            sheet.addMergedRegion(new CellRangeAddress(0, 0, objectiveStartCol, objectiveStartCol + objectiveCount - 1));
            firstLevelHeaders[objectiveStartCol] = "客观总得分";
        }else if (objectiveCount == 1) {
            firstLevelHeaders[objectiveStartCol] = "客观总得分";
        }

        int subjectiveStartCol = objectiveStartCol + objectiveCount;
        if (subjectiveCount > 1) {
            sheet.addMergedRegion(new CellRangeAddress(0, 0, subjectiveStartCol, subjectiveStartCol + subjectiveCount - 1));
            firstLevelHeaders[subjectiveStartCol] = "主观总得分";
        }else if (subjectiveCount == 1) {
            firstLevelHeaders[subjectiveStartCol] = "主观总得分";
        }

        // 设置固定表头
        for (int i = 0; i < firstLevelHeaderLength; i++) {
            if (firstLevelHeaders[i] != null) {
                Cell cell = row0.createCell(i);
                cell.setCellValue(firstLevelHeaders[i]);
                cell.setCellStyle(headerStyle);
            }
        }


        // 第二行表头
        Row row1 = sheet.createRow(1);

        // 设置固定部分
        String[] secondLevelHeaders = {"", "", "","总分", "客观分", "主观分"};
        for (int i = 0; i < secondLevelHeaders.length; i++) {
            Cell cell = row1.createCell(i);

            cell.setCellValue(secondLevelHeaders[i]);
            cell.setCellStyle(headerStyle);
        }
        // 定义正则表达式模式（在循环外创建以提高性能）
        // 设置客观题表头
        int colIndex = 6;
        for (String question : allObjectiveQuestions) {
            Cell cell = row1.createCell(colIndex++);
            cell.setCellValue(question);
            cell.setCellStyle(headerStyle);
        }
        // 设置主观题表头
        for (String question : allSubjectiveQuestions) {
            Cell cell = row1.createCell(colIndex++);
            cell.setCellValue(question);
            cell.setCellStyle(headerStyle);
        }

        // 3. 填充数据行
        int rowIndex = 2;
        for (Map<String, Object> data : dataList) {
            Row row = sheet.createRow(rowIndex++);

            Cell nameCell = row.createCell(0);
            nameCell.setCellValue((String) data.get("name"));
            nameCell.setCellStyle(dataStyle);
            Cell examRankCell = row.createCell(1);
            if(type == 0) {
                examRankCell.setCellValue((int) data.get("gradeRank"));
            }else {
                examRankCell.setCellValue((int) data.get("overallRank"));
            }

            Cell rankCell = row.createCell(2);
            if(type == 0) {
                rankCell.setCellValue((int) data.get("rank"));
            }else {
                rankCell.setCellValue((int) data.get("classRank"));
            }
            rankCell.setCellStyle(dataStyle);

            examRankCell.setCellStyle(dataStyle);
            Cell totalScoreCell = row.createCell(3);
            totalScoreCell.setCellValue((String) data.get("totalScore"));
            totalScoreCell.setCellStyle(dataStyle);

            Cell objectiveScoreCell = row.createCell(4);
            objectiveScoreCell.setCellValue((String) data.get("objectiveScore"));
            objectiveScoreCell.setCellStyle(dataStyle);

            Cell subjectiveScoreCell = row.createCell(5);
            subjectiveScoreCell.setCellValue((String) data.get("subjectiveScore"));
            subjectiveScoreCell.setCellStyle(dataStyle);

            // 客观题得分
            colIndex = 6;
            Map<String, Double> objectiveMap = new LinkedHashMap<>();
            if (type == 0) {
                objectiveMap = (Map<String, Double>) data.get("objectiveMap");
            }else {
                List<Map<String, Object>> objList = (List<Map<String, Object>>) data.get("objectiveMap");
                for(Map<String, Object> item : objList) {
                    objectiveMap.put((String) item.get("questionNum"), (Double) item.get("score"));
                }
            }
            for (String question : allObjectiveQuestions) {
                Cell cell = row.createCell(colIndex++);
                // 获取分数值并处理为合适的类型
                Object scoreObj = objectiveMap.getOrDefault(question, 0.0);
                double score = 0.0;
                if (scoreObj instanceof Number) {
                    score = ((Number) scoreObj).doubleValue();
                } else if (scoreObj instanceof String) {
                    try {
                        score = Double.parseDouble((String) scoreObj);
                    } catch (NumberFormatException e) {
                        // 处理格式错误，默认为0
                    }
                }

                cell.setCellValue(score);
                cell.setCellStyle(dataStyle);
            }


            // 主观题得分
            Map<String, Double> subjectiveMap = new LinkedHashMap<>();
            if (type == 0) {
                subjectiveMap = (Map<String, Double>) data.get("subjectiveMap");
            }else {
                List<Map<String, Object>> objList = (List<Map<String, Object>>) data.get("subjectiveMap");
                for(Map<String, Object> item : objList) {
                    subjectiveMap.put((String) item.get("questionNum"), (Double) item.get("score"));
                }
            }
            for (String question : allSubjectiveQuestions) {
                Cell cell = row.createCell(colIndex++);

                Object scoreObj = subjectiveMap.getOrDefault(question, 0.0);
                double score = 0.0;

                if (scoreObj instanceof Number) {
                    score = ((Number) scoreObj).doubleValue();
                } else if (scoreObj instanceof String) {
                    try {
                        score = Double.parseDouble((String) scoreObj);
                    } catch (NumberFormatException e) {
                        // 处理格式错误，默认为0
                    }
                }

                cell.setCellValue(score);
                cell.setCellStyle(dataStyle);
            }
        }

        // 4. 设置列宽
        for (int i = 0; i < colIndex; i++) {
            sheet.setColumnWidth(i, 6 * 256); // 大致设置列宽
        }

        // 5. 写入文件
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            workbook.write(fos);
            System.out.println("Excel 文件生成成功，路径：" + filePath);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Excel 文件生成失败");
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static String processQuestionName(String question, Pattern questionPattern, Pattern numberPattern) {
        // 处理形如 "11-解答题-1" 的格式
        Matcher matcher = questionPattern.matcher(question);
        if (matcher.matches()) {
            return matcher.group(1) + "-" + matcher.group(3); // 保留前后数字，去掉题型
        }

        // 处理形如 "填空题-10" 的格式
        matcher = numberPattern.matcher(question);
        if (matcher.matches()) {
            return matcher.group(1); // 只保留数字部分
        }

        // 其他格式保持不变
        return question;
    }

    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 13);
        style.setWrapText(true);
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 启用填充模式
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }

    private static CellStyle createDataStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 11);
        style.setFont(font);
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }
}